import serial
import os
"""
    文件名：
        MCUUARTpyByCYL.py
    文件说明：
        完全通用的MCU-UART通讯工程py文件。除了MCUpyUARTConnect()中的[0]里的内容。
"""
def findSerialPort()->str:
    """
        2021-08-31  13:31   by  炸天帮成员
        函数名：
            findSerialPort()
        函数用途：
            用于查询电脑端可用的串口。
        类型：
            通用型函数。
    :return:    返回一个字符串，内容为有挂载的串口号。
    """
    serial_ports = os.popen('python -m serial.tools.list_ports').read().strip()  # 调用控制台并读取cmd命令行的结果
    print('serial_ports = ', serial_ports,type(serial_ports))  # 显示当前有效的COM端
    return serial_ports

def serial_Port_Init(serial_ports:str)->serial.serialwin32.Serial:
    """
        2021-08-31  13:33   by  炸天帮成员
        函数名：
            serial_Port_Init()
        函数用途：
            用于设置UART的通讯参数。
        类型：
            通用型函数。
    :param serial_ports:    为一个有挂载的串口端口号，一般来自findSerialPort()。
    :return:                serial.serialwin32.Serial类型的对象。
    """
    ser = serial.Serial()       # 实例化serial_com端口
    ser.port = serial_ports     # 设置端口号
    ser.baudrate = 115200       # 设置端口的波特率115200
    ser.bytesize = serial.EIGHTBITS
    ser.parity = serial.PARITY_NONE
    ser.stopbits = serial.STOPBITS_ONE
    ser.timeout = 0.01          # 设定读取超时时间0.01s
    ser.xonxoff = False
    ser.rtscts = False
    ser.write_timeout = None    # Set a write timeout value.
    ser.dsrdtr = False
    ser.inter_byte_timeout = None
    print("ser = ",ser,type(ser))  # 输出当前端口的详细信息
    return ser

def readBytesFromUART(targetSerial:serial.serialwin32.Serial)->str:
    """
        2021-08-31  13:35   by  炸天帮成员
        函数名：
            readBytesFromUART()
        函数用途：
            用于获取来自UART返回值。
        类型：
            单次通用型函数。
    :param targetSerial:    一般为下位机所在的端口号所对应的serial.serialwin32.Serial类型的对象。一般来自serial_Port_Init()。
    :param repeatTime:      xxx.read()重复扫描的次数，间隔时间在serial_Port_Init()中的timeout中设置。可以在一定程度上解决EOF遇到0x0d0x0a后的问题。
    :return:    来自UART的字符串结果。
    """
    data_return = targetSerial.read()   # 可以按字节数读取来自下位机的串口内容，此处设定为100字节
    print('data_return = ', data_return)  # 显示从COM端读取到的内容
    data_in_waiting = targetSerial.read(targetSerial.in_waiting)
    print('ser.in_waiting =', data_in_waiting)
    result = data_return + data_in_waiting
    print('uart结果为：', result.decode(encoding="UTF-8"))
    return result

def sendStringToUART(targetSerial:serial.serialwin32.Serial,theContent: str):
    """
        2021-08-31  13:41   BY  炸天帮成员
        函数名：
            sendStringToUART()
        函数用途：
            用于向MCU中传入Bytes字节流，并得到其返回值。
        函数类型：
            无读取功能的通用型函数。
            后续可以加一个readBytesFromUART()。
    :param targetSerial:一般为MCU所在的端口号所对应的serial.serialwin32.Serial类型的对象。一般来自serial_Port_Init()。
    :param theContent:  用于向MCU中传入Bytes字节流所对应的字符串内容。
    :return:            无。
    """
    send_bytes = bytes(theContent, encoding='UTF-8') + b'\x0d\x0a'
    send_string = send_bytes.decode('UTF-8')
    print('send_bytes = ', send_bytes, 'send_bytes 的类型为：', type(send_bytes), '\nsend_string = ', send_string,
          ' send_string 的类型为', type(send_string))
    targetSerial.write(send_bytes)  # 发送数据至MCU

def MCUpyUARTConnect(targetSerial:serial.serialwin32.Serial):
    """
        2021-08-31  14:04   by  炸天帮成员
        函数名：
            MCUpyUARTConnect()
        函数说明：
            使用通用型函数适配ESP8266芯片。
        函数类型：
            修改[0]中的所有内容，即可成为其余芯片UART的代码。
    :param targetSerial:    serial.serialwin32.Serial对象，一般由serial_Port_Init()获得。
    :return:                无。
    """
    targetSerial.open()
    if targetSerial.is_open:
        #[0]通用型函数适配ESP8266芯片，进行UART数据的读写。
        sendStringToUART(targetSerial=targetSerial,theContent = "import machine")
        readBytesFromUART(targetSerial=targetSerial)
        readBytesFromUART(targetSerial=targetSerial)

        sendStringToUART(targetSerial=targetSerial,theContent = "machine.freq()")
        readBytesFromUART(targetSerial=targetSerial)
        readBytesFromUART(targetSerial=targetSerial)
        #其他写读UART数据的操作。
    targetSerial.close()